const WebSocket = require('ws');
const JWT = require('../utils/jwt');
const Message = require('../models/message');
const User = require('../models/user');
const Product = require('../models/product');
const mongoose = require('mongoose');

class ChatServer {
  constructor(server) {
    this.wss = new WebSocket.Server({
      server,
      perMessageDeflate: false,
      maxPayload: 5 * 1024 * 1024 // 5MB
    });

    // 存储用户连接
    this.connections = new Map(); // userId -> WebSocket

    this.wss.on('connection', this.handleConnection.bind(this));
    console.log('WebSocket服务器已启动');
  }

  // 生成会话ID
  generateSessionId(buyerId, sellerId, productId) {
    return [buyerId, sellerId, productId].map(id => id.toString()).join('-');
  }

  // 处理新连接
  async handleConnection(ws, req) {
    try {
      const token = new URL(req.url, 'ws://localhost').searchParams.get('token');
      if (!token) {
        throw new Error('未提供token');
      }

      const userInfo = JWT.verify(token);
      if (!userInfo) {
        throw new Error('无效的token');
      }

      const user = await User.findById(userInfo.userId);
      if (!user) {
        throw new Error('用户不存在');
      }

      // 存储连接信息
      ws.userId = userInfo.userId;
      ws.userInfo = {
        userId: user._id,
        username: user.username,
        avatar: user.avatar
      };
      this.connections.set(userInfo.userId, ws);

      console.log(`用户已连接: ${user.username} (ID: ${user._id})`);

      // 设置事件处理器
      ws.on('message', data => this.handleMessage(ws, data));
      ws.on('close', () => this.handleClose(ws));
      ws.on('error', error => this.handleError(ws, error));

    } catch (error) {
      this.sendError(ws, error.message);
      ws.close();
    }
  }

  // 处理连接关闭
  handleClose(ws) {
    if (ws.userId) {
      this.connections.delete(ws.userId);
      console.log(`用户断开连接: ${ws.userInfo.username} (ID: ${ws.userId})`);
    }
  }

  // 处理连接错误
  handleError(ws, error) {
    console.error(`WebSocket错误 (${ws.userInfo?.username || 'Unknown'}):`, error);
  }

  // 处理消息
  async handleMessage(ws, data) {
    try {
      const message = JSON.parse(data);

      if (!message.type || typeof message.type !== 'string') {
        throw new Error('无效的消息格式：type必须是字符串');
      }

      if (!message.data || typeof message.data !== 'object') {
        throw new Error('无效的消息格式：data必须是对象');
      }

      console.log(`处理消息类型: ${message.type}`);

      const handlers = {
        'initChat': () => this.handleInitChat(ws, message.data),
        'sendMessage': () => this.handleSendMessage(ws, message.data),
        'getHistory': () => this.handleGetHistory(ws, message.data),
        'getSessions': () => this.handleGetSessions(ws)
      };

      const handler = handlers[message.type];
      if (!handler) {
        throw new Error(`未知的消息类型: ${message.type}`);
      }

      await handler();
    } catch (error) {
      console.error('处理消息时发生错误:', error);
      this.sendError(ws, error.message);
    }
  }

  // 处理初始化聊天
  async handleInitChat(ws, { productId }) {
    try {
      const product = await Product.findById(productId).populate('seller');
      if (!product) {
        throw new Error('商品不存在');
      }

      const sessionId = this.generateSessionId(ws.userId, product.seller._id, productId);

      this.send(ws, {
        type: 'chatInitiated',
        data: {
          sessionId,
          product: {
            id: product._id,
            title: product.title,
            price: product.price,
            image: product.images[0]
          },
          seller: {
            id: product.seller._id,
            name: product.seller.username,
            avatar: product.seller.avatar
          }
        }
      });
    } catch (error) {
      throw new Error(`初始化聊天失败: ${error.message}`);
    }
  }

  // 发送消息
  async handleSendMessage(ws, { sessionId, content, type = 'text' }) {
    try {
      const [buyerId, sellerId, productId] = sessionId.split('-');

      // 验证发送者身份
      if (ws.userId !== buyerId && ws.userId !== sellerId) {
        throw new Error('您不是该会话的参与者');
      }

      // 确定接收者（如果当前用户是买家，接收者就是卖家，反之亦然）
      const message = new Message({
        sessionId,
        sender: ws.userId,
        receiver: ws.userId === buyerId ? sellerId : buyerId,
        product: productId,
        content,
        type
      });

      await message.save();

      const formattedMessage = await this.formatMessage(message);

      // 发送给接收者
      const receiverWs = this.connections.get(message.receiver);
      if (receiverWs) {
        this.send(receiverWs, {
          type: 'newMessage',
          data: formattedMessage
        });
      }

      // 发送确认给发送者
      this.send(ws, {
        type: 'messageSent',
        data: formattedMessage
      });
    } catch (error) {
      throw new Error(`发送消息失败: ${error.message}`);
    }
  }

  // 获取历史消息
  async handleGetHistory(ws, { sessionId, before, limit = 20 }) {
    try {
      console.log('获取历史消息:', {
        sessionId,
        userId: ws.userId,
        before,
        limit
      });

      // 验证sessionId格式
      const [buyerId, sellerId, productId] = sessionId.split('-');

      // 验证ID的有效性
      if (!buyerId || !sellerId || !productId) {
        throw new Error('无效的会话ID格式');
      }

      // 验证买家和卖家不能是同一个人
      if (buyerId === sellerId) {
        throw new Error('买家和卖家不能是同一个人');
      }

      // 验证用户是否是会话参与者
      if (ws.userId !== buyerId && ws.userId !== sellerId) {
        throw new Error('您不是该会话的参与者');
      }

      // 构建查询条件
      const query = {
        $or: [
          { sessionId },
          // 处理可能的ID顺序不同的情况
          { sessionId: `${sellerId}-${buyerId}-${productId}` }
        ]
      };

      if (before) {
        query.createdAt = { $lt: new Date(before) };
      }

      console.log('查询条件:', JSON.stringify(query, null, 2));

      // 确保ID转换为ObjectId
      const messages = await Message.find(query)
        .sort('-createdAt')
        .limit(limit)
        .populate('sender', 'username avatar')
        .populate('receiver', 'username avatar')
        .lean();

      console.log('查询到的消息数量:', messages.length);

      if (messages.length === 0) {
        console.log('未找到消息，进行额外检查');

        // 检查产品是否存在
        const product = await Product.findById(productId).lean();
        console.log('产品是否存在:', !!product);

        // 检查用户是否存在
        const [buyer, seller] = await Promise.all([
          User.findById(buyerId).lean(),
          User.findById(sellerId).lean()
        ]);
        console.log('买家是否存在:', !!buyer);
        console.log('卖家是否存在:', !!seller);

        // 直接查询所有相关消息（不带其他条件）
        const allMessages = await Message.find({
          $or: [
            { sessionId },
            { sessionId: `${sellerId}-${buyerId}-${productId}` }
          ]
        }).lean();

        console.log('数据库中相关消息总数:', allMessages.length);
        if (allMessages.length > 0) {
          console.log('示例消息:', allMessages[0]);
        }
      }

      const formattedMessages = messages.map(msg => {
        const formatted = this.formatMessageLean(msg);
        console.log('格式化后的消息:', formatted);
        return formatted;
      });

      const hasMore = messages.length === limit;

      this.send(ws, {
        type: 'history',
        data: {
          messages: formattedMessages,
          hasMore
        }
      });

      // 标记消息为已读
      if (messages.length > 0) {
        const updateResult = await Message.updateMany(
          {
            $or: [
              { sessionId },
              { sessionId: `${sellerId}-${buyerId}-${productId}` }
            ],
            receiver: ws.userId,
            isRead: false
          },
          {
            $set: { isRead: true }
          }
        );
        console.log('更新已读状态结果:', updateResult);
      }
    } catch (error) {
      console.error('获取历史消息失败:', error);
      throw new Error(`获取历史消息失败: ${error.message}`);
    }
  }

  // 获取会话列表
  async handleGetSessions(ws) {
    try {
      const userId = ws.userId;
      console.log('正在获取会话列表，用户ID:', userId);

      // 确保userId是ObjectId类型
      const userObjectId = new mongoose.Types.ObjectId(userId);

      // 首先获取所有相关的sessionId
      const distinctSessions = await Message.distinct('sessionId', {
        $or: [
          { sender: userObjectId },
          { receiver: userObjectId }
        ]
      });

      console.log('找到的不同会话:', distinctSessions);

      // 对每个会话获取最后一条消息和未读数
      const sessionsData = await Promise.all(distinctSessions.map(async (sessionId) => {
        // 获取最后一条消息
        const lastMessage = await Message.findOne({ sessionId })
          .sort('-createdAt')
          .lean();

        // 获取未读消息数
        const unreadCount = await Message.countDocuments({
          sessionId,
          receiver: userObjectId,
          isRead: false
        });

        return {
          sessionId,
          lastMessage,
          unreadCount
        };
      }));

      console.log('会话数据初步处理:', sessionsData.length);

      // 处理每个会话的详细信息
      const sessions = await Promise.all(sessionsData.map(async (session) => {
        const [buyerId, sellerId, productId] = session.sessionId.split('-');
        console.log('处理会话:', {
          sessionId: session.sessionId,
          buyerId,
          sellerId,
          productId
        });

        try {
          // 确保ID转换为ObjectId
          const productObjectId = new mongoose.Types.ObjectId(productId);
          const otherUserId = userObjectId.toString() === buyerId ? sellerId : buyerId;
          const otherUserObjectId = new mongoose.Types.ObjectId(otherUserId);

          const [product, otherUser] = await Promise.all([
            Product.findById(productObjectId).select('title price images status').lean(),
            User.findById(otherUserObjectId).select('username avatar status').lean()
          ]);

          if (!product || !otherUser) {
            console.log('会话数据不完整，跳过:', {
              hasProduct: !!product,
              hasUser: !!otherUser,
              sessionId: session.sessionId
            });
            return null;
          }

          return {
            sessionId: session.sessionId,
            product: {
              id: product._id,
              title: product.title,
              price: product.price,
              image: product.images[0],
              status: product.status
            },
            otherUser: {
              id: otherUser._id,
              name: otherUser.username,
              avatar: otherUser.avatar,
              status: otherUser.status
            },
            lastMessage: session.lastMessage ? this.formatMessageLean(session.lastMessage) : null,
            unreadCount: session.unreadCount,
            updatedAt: session.lastMessage?.createdAt
          };
        } catch (error) {
          console.error('处理单个会话时出错:', error);
          return null;
        }
      }));

      const validSessions = sessions.filter(Boolean);
      console.log('最终有效会话数量:', validSessions.length);

      // 按最后更新时间排序
      validSessions.sort((a, b) => b.updatedAt - a.updatedAt);

      this.send(ws, {
        type: 'sessions',
        data: {
          sessions: validSessions
        }
      });
    } catch (error) {
      console.error('获取会话列表失败:', error);
      throw new Error(`获取会话列表失败: ${error.message}`);
    }
  }

  // 格式化消息（用于Mongoose文档）
  async formatMessage(message) {
    const populated = await message.populate([
      { path: 'sender', select: 'username avatar' },
      { path: 'receiver', select: 'username avatar' }
    ]);

    return this.formatMessageLean(populated);
  }

  // 格式化消息（用于普通对象）
  formatMessageLean(message) {
    return {
      id: message._id,
      content: message.content,
      type: message.type,
      sender: {
        id: message.sender._id,
        name: message.sender.username,
        avatar: message.sender.avatar
      },
      receiver: {
        id: message.receiver._id,
        name: message.receiver.username,
        avatar: message.receiver.avatar
      },
      createdAt: message.createdAt,
      isRead: message.isRead
    };
  }

  // 发送消息
  send(ws, data) {
    if (ws && ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(data));
    }
  }

  // 发送错误
  sendError(ws, message) {
    this.send(ws, {
      type: 'error',
      data: { message }
    });
  }
}

module.exports = ChatServer; 